import { TextNode, StrongNode, EmphNode, DelNode, ParagraphNode, ImgNode, LinkNode } from './mnodes'
import DelimitersStack from "./delimiter-stack";
export default class MarkdownParserLine {
    static textReg = /^[^\[\]*_~]+/m; // 普通文本
    constructor() {
        this.offset_ = 0;
        this.delimiter_ = null;
        this.line_ = '';
        this.mnode_ = null; // 最后生成的节点树
    }
    parse(line) {
        this.offset_ = 0;
        this.delimiter_ = null;
        this.mnode_ = new ParagraphNode();
        this.line_ = line;
        this.parseLine_();
        this.transNormal_();
        return this.mnode_;
    }
    match_(reg) {
        const matched = reg.exec(this.line_.slice(this.offset_));
        if (matched) {
            this.offset_ += matched[0].length;
            return matched[0];
        } else {
            return null;
        }
    }
    parseLine_() {
        let char = '';
        while (char = this.line_[this.offset_]) {
            switch (char) {
                case '*':
                case '_':
                case '~':
                    this.parseNormal_(char);
                    break;
                case '[':
                    this.parseOpenBracket_();
                    break;
                case ']':
                    this.parseCloseBracket_();
                    break;
                default:
                    this.parseText_();
            }
        }
    }
    parseOpenBracket_() {
        let char  = '[';
        this.offset_++;

         // 分隔符入栈
         const textNode = new TextNode(char)
         this.mnode_.appendChild(textNode);
         const delimiter = new DelimitersStack(char, 1, textNode);
         if (this.delimiter_) {
             this.delimiter_.next = delimiter;
             delimiter.pre = this.delimiter_;
         }
         this.delimiter_ = delimiter;
        
    }
    parseCloseBracket_() {
        let opener = this.delimiter_;
        let isImage = false;
        let startPos = this.offset_;
        while (opener) {
            if (opener.char === '[') {
                break;
            }
            if (opener.char === '![') {
                isImage = true;
                break;
            }
            opener = opener.pre;
        }
        if (!opener) {
            this.mnode_.appendChild(new TextNode(']'));
            return;
        }
        // 如果中括号匹配成功
        this.offset_++;
        let dest = '';
        let matched = false;
        if (this.line_[this.offset_] === '(') {
            this.offset_++;
            let char;
            while (char = this.line_[this.offset_]) {
                if (char !== ')') {
                    dest += char;
                } else {
                    matched = true;
                    break;
                }
                this.offset_++;
            }
        }
        if (matched) {
            const mynode = isImage ? new ImgNode(dest) : new LinkNode(dest);
            // todo 
            // 1、把opener和closer之间（即[]之间）的主节点
            // 2、把mynode append到主节点链路（mnode.appendChild(mynode)）
            // 3、把opener和closer之间的分隔符继续做加粗、斜体、删除线的解析识别（this.transNormal_(opener)）
            // 4、移除消耗掉的分隔符
            

        } else {
            if (this.delimiter_ === opener) {
                this.delimiter_ = opener.pre;
            }
            opener.remove();
            this.offset_ = startPos;
            this.mnode_.appendChild(new TextNode(']'));
        }

    }
    parseNormal_(char) {
        let count = 0;
        let startPos = this.offset_; // 记录原始位置
        while (this.line_[this.offset_] === char) {
            count++;
            this.offset_++;
        }
        // 分隔符入栈
        const textNode = new TextNode(this.line_.substr(startPos, count))
        this.mnode_.appendChild(textNode);
        const delimiter = new DelimitersStack(char, count, textNode);
        if (this.delimiter_) {
            this.delimiter_.next = delimiter;
            delimiter.pre = this.delimiter_;
        }
        this.delimiter_ = delimiter;
    }
    parseText_() {
        const matchText = this.match_(MarkdownParserLine.textReg);
        if (matchText) {
            this.mnode_.appendChild(new TextNode(matchText));
        }
    }
    // 转换对称标识符为节点（加粗、删除线、斜体等）
    transNormal_(stackBottom) {
        let closer = this.delimiter_;
        let opener = null;
        // 栈底的标识符
        while (closer !== null && closer.pre !== stackBottom) {
            closer = closer.pre;
        }
        // 从栈底往上找到符合要求的标识符
        while (closer) {
            const char = closer.char;
            if (char === '*' || char === '_' || char === '~') {
                // 往栈底去找符合要求的开始标识符
                opener = this.transNormalOperner_(closer);
                if (opener) {
                    // 发现opener，转换成节点，并删除已经用过的标识符，同时把opener和closer之间原有的内容，包含的新的节点中去
                    let usedCount = 0; // 记录消耗掉的标识符数量
                    const openerNode = opener.mnode;
                    const closerNode = closer.mnode;
                    let transNode = null; // 根据标识符配对生成的节点
                    if (char === '*' || char === '_') {
                        if (opener.currentCount >= 2 && closer.currentCount >= 2) {
                            transNode = new StrongNode();
                            usedCount = 2;
                        } else {
                            transNode = new EmphNode();
                            usedCount = 1;
                        }
                    } else {
                        usedCount = 1;
                        transNode = new DelNode();
                    }
                    // 消耗掉的分割符
                    opener.currentCount -= usedCount;
                    openerNode.text = openerNode.text.slice(usedCount);

                    closer.currentCount -= usedCount;
                    closerNode.text = closerNode.text.slice(usedCount);

                    // 把opener和closer之间的内容，包含到新节点中去
                    let betweenNode = openerNode.next;
                    let next;
                    while (betweenNode && betweenNode !== closerNode) {
                        next = betweenNode.next;
                        // betweenNode.unlink();
                        transNode.appendChild(betweenNode);
                        betweenNode = next;
                    }
                    // 将失败转换后的节点，插入到节点树中去
                    openerNode.insertAfter(transNode);
                    // opener 和 closer 之间的其他分隔符将作为普通文本显示，没有机会去匹配转换了，因此从链表移除
                    DelimitersStack.removeBetween(opener, closer);
                    // 分隔符呗消耗后，剩余分隔符数量为0时，其对应的节点都没必要保留了
                    if (opener.currentCount === 0) {
                        opener.remove();
                        openerNode.unlink();
                    }
                    if (closer.currentCount === 0) {
                        // closer 需要后移，用于后续继续匹配
                        const nextCloser = closer.next;
                        if (this.delimiter_ === closer) {
                            this.delimiter_ = closer.pre;
                        }
                        closer.remove();
                        closer = nextCloser;
                        closerNode.unlink();
                    }
                } else {
                    // 没有找到opener,则当前closer无法作为闭合标识符，后移closer
                    closer = closer.next;
                }
            } else {
                closer = closer.next;
            }
        }

    }
    // 根据closer 往前面找到符合要求的opener
    transNormalOperner_(closer) {
        let opener = closer.pre;
        while (opener && opener !== null) {
            if (opener.char === closer.char) {
                return opener;
            } else {
                opener = opener.pre;
            } 
        }
    }  
}